#include "main.h"
#include <string.h>

std::string cons::to_string_(bool isin)
{
    std::string cars = car->to_string();

    if (boost::dynamic_pointer_cast<cons>(cdr)) {
	std::string cdrs = boost::dynamic_pointer_cast<cons>(cdr)->to_string_();
   	return isin ? cars + " " + cdrs : "(" + cars + " " + cdrs + ")";
    } else if (cdr->to_string() == "false")
   	return isin ? cars : "(" + cars + ")";
    std::string cdrs = cdr->to_string();
    return isin ? cars + " . " + cdrs : "(" + cars + " . " + cdrs + ")";

}

std::string cons::to_string()
{
    return to_string_(false);
}

Object cons::eval(Environment env)
{
    try {
	env->get_value(car->to_string())->set_arg(cdr);
	return env->get_value(car->to_string())->eval(env);
    } catch (...) {
	if (car->get_type() == "#<String>") {
	    std::string str = car->to_string();
	    if (str[1] == 'c') {
		if (str[str.length() - 2] == 'r') {
		    Object arg = cdr->get_car()->eval(env);
		    for (int i = str.length() - 3; 0 < i; i--)
			if (str[i] == 'a')
			    arg = arg->get_car();
			else if (str[i] == 'd')
			    arg = arg->get_cdr();
			else if (str[i] == 'c')
			    if (str[i - 1] != '\"')
				break;
			    else
				return arg;
			else
			    break;
		}
	    }
	} else if (env->get_value(car->to_string())->get_car() == env->get_value("lambda")) {
	    Object obj, ret;
	    env->bind_arg(env, cdr);
	    for (obj = env->get_value(car->to_string())->get_cdr(); obj->to_string() != "false"; obj = obj->get_cdr())
		ret = obj->get_car()->eval(env);
	    env->auto_remove();
	    return ret;
	}
    }
    throw Error(new error(error::notfunc));
}
